﻿// KittyFeral PVE - HB Routine for FeralDruid 5.4 - By Neyia
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;
using Action = Styx.TreeSharp.Action;


namespace KittyFeral
{
    public partial class Main : CombatRoutine
    {
        public override string Name { get { return "KittyFeral - PVE 5.4"; } }
        public override WoWClass Class { get { return WoWClass.Druid; } }
        public LocalPlayer Me { get { return StyxWoW.Me; } }

        
        public override Composite CombatBehavior { get { return CreateCombat(); } }
        public override Composite PullBehavior { get { return CreatePull(); } }
        public override Composite PullBuffBehavior { get { return CreatePullBuffs(); } }
        public override Composite PreCombatBuffBehavior { get { return CreateBuffs(); } }
        public override Composite CombatBuffBehavior { get { return CreateBuffs(); } }
        public override Composite MoveToTargetBehavior { get { return CreateMovementBehavior(); } }

        #region Delegates
        public delegate WoWPoint LocationRetriverDelegate(object context);
        #endregion

        public string LastSpell = string.Empty;
        public bool isBoss { get { return IsWoWBoss(StyxWoW.Me.CurrentTarget); } }
        public bool Solo { get { return SoloOrNot(); } }
        public int addCount { get { return UnfriendlyUnits.Count(); } }
        public string shapeForm = string.Empty;
        public string usedBot { get { return BotManager.Current.Name.ToUpper(); } }

        

        #region show form
        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }
        #endregion

        #region initialize
        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            Updater.CheckForUpdate(UpdateSettingsKittyFeral.myPrefs.Revision);
            EventHandlers.AttachCombatLogEvent();

        }
        #endregion

        #region pulse
        public override void Pulse()
        {
            try
            {
                if (Me.IsDead
                    && usedBot.Contains("QUEST") || usedBot.Contains("GRIND"))
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                }
                if (Me.CurrentTarget != null && (Me.CurrentTarget.OwnedByUnit.IsPlayer && !Me.CurrentTarget.OwnedByUnit.IsMe))
                {
                    Me.ClearTarget();
                }
                if (Me.Mounted && usedBot.Contains("QUEST") && (Me.CurrentTarget != null && Me.Combat))
                {
                    Lua.DoString("Dismount()");
                }
                
                return;
            }
            catch { }
        }
        #endregion

        #region shutdown
        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            EventHandlers.DetachCombatLogEvent();
        }
        #endregion

        #region pull buffs
        Composite CreatePullBuffs()
        {
            return 
                new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                Cast(BEAR_FORM, ret => Me.Specialization == WoWSpec.DruidGuardian && Me.Shapeshift != ShapeshiftForm.Bear),
                Cast(BEAR_FORM, ret => Me.Specialization == WoWSpec.DruidFeral && useBearForm() && Me.Shapeshift != ShapeshiftForm.Bear),
                Cast(CAT_FORM, ret => Me.Specialization == WoWSpec.DruidFeral && useCatForm() && Me.Shapeshift != ShapeshiftForm.Cat),
                Cast(MOONKIN_FORM, ret => Me.Specialization == WoWSpec.DruidBalance && Me.Shapeshift != ShapeshiftForm.Moonkin),
                Cast(PROWL, ret => CRSettingsCat.myPrefs.useProwlPounce && !buffExists(PROWL, Me) && !spellOnCooldown(PROWL) && SpellManager.HasSpell(POUNCE))
                );
        }
        #endregion

        #region create pull
        Composite CreatePull()
        {
            return 
                new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                new Decorator(ret => IsCrowdControlledPlayer(Me), RemoveRooted()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidGuardian, BearPull()),
                new Decorator(ret => gotTarget && (Me.Specialization == WoWSpec.None && !SpellManager.HasSpell(CAT_FORM)), LowbiePull()),
                new Decorator(ret => gotTarget && SpellManager.HasSpell(BEAR_FORM) && useBearForm(), BearPull()),
                new Decorator(ret => gotTarget && SpellManager.HasSpell(CAT_FORM) && useCatForm(), CatPull())
                );
        }
        #endregion

        #region lowbie pull
        Composite LowbiePull()
        {
            return 
                new PrioritySelector(
                    FaceMyTarget(),
                    new Decorator(ret => gotTarget && Me.CurrentTarget.Distance > myRange, CreateMovementBehavior()),
                    Cast(MOONFIRE, ret => gotTarget && Me.CurrentTarget.Distance <= 38),
                    Cast(WRATH, ret => gotTarget && Me.CurrentTarget.Distance <= 38)
                );
        }
        #endregion

        #region bear pull
        Composite BearPull()
        {
            return 
                new PrioritySelector(
                Cast(BEAR_FORM, ret => Me.Shapeshift != ShapeshiftForm.Bear),
                FaceMyTarget(),
                new Decorator(ret => gotTarget && Me.CurrentTarget.Distance > myRange, CreateMovementBehavior()),
                CastWildCharge(WILD_CHARGE, ret => gotTarget 
                    && CRSettingsBear.myPrefs.useWildCharge
                    && SpellManager.HasSpell(WILD_CHARGE) 
                    && !spellOnCooldown(WILD_CHARGE) 
                    && Me.CurrentTarget.InLineOfSight 
                    && CanCastWildCharge(8, 25)),
                Cast(FAERIE_FIRE, ret => gotTarget && !spellOnCooldown(FAERIE_FIRE) && Me.CurrentTarget.Distance <= 35),
                Cast(GROWL, ret => gotTarget && !spellOnCooldown(GROWL) && Me.CurrentTarget.Distance <= 35),
                CastMelee(LACERATE, ret => gotTarget && !spellOnCooldown(LACERATE) && Me.CurrentTarget.Distance <= 4),
                CastMelee(MANGLE, ret => gotTarget && !spellOnCooldown(MANGLE) && Me.CurrentTarget.Distance <= 4),
                CastMelee(MAUL, ret => gotTarget && !spellOnCooldown(MAUL) && Me.CurrentTarget.Distance <= 4),
                CastMelee(THRASH, ret => gotTarget && !spellOnCooldown(THRASH) && Me.CurrentTarget.Distance <= 4)
                );
        }
        #endregion

        #region catpull
        Composite CatPull()
        {
            return 
                new PrioritySelector(
                Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat),
                FaceMyTarget(),
                new Decorator(ret => gotTarget && Me.CurrentTarget.Distance > myRange, CreateMovementBehavior()),
                Cast(POUNCE, ret => gotTarget && buffExists(PROWL, Me)
                    && Me.EnergyPercent >= 50
                    && Me.CurrentTarget.Distance <= 4
                    && !Unit.IsAboveTheGround(Me.CurrentTarget)),
                CastWildCharge(WILD_CHARGE, ret => gotTarget
                    && !spellOnCooldown(WILD_CHARGE) 
                    && CRSettingsCat.myPrefs.useWildCharge
                    && Me.CurrentTarget.InLineOfSight 
                    && CanCastWildCharge(8, 25)),
                Cast(FAERIE_FIRE, ret => gotTarget 
                    && !spellOnCooldown(FAERIE_FIRE) 
                    && Me.CurrentTarget.Distance <= 34 && (!buffExists(PROWL, Me) || Unit.IsAboveTheGround(Me.CurrentTarget) || !SpellManager.HasSpell(POUNCE))),
                Cast(POUNCE, ret => gotTarget
                    && SpellManager.HasSpell(POUNCE)
                    && buffExists(PROWL, Me)
                    && Me.EnergyPercent >= 50
                    && Me.CurrentTarget.Distance <= 4),
                Cast(MANGLE, ret => gotTarget && Me.CurrentTarget.Distance <= 4 && (!buffExists(PROWL, Me) || !SpellManager.HasSpell(POUNCE)))
                );
        }
        #endregion

        #region buffs
        Composite CreateBuffs()
        {
            return 
                new PrioritySelector(
                new Decorator(ret => Paused, PauseCR()),
                Cast(MOONKIN_FORM, ret => Me.Specialization == WoWSpec.DruidBalance && Me.Shapeshift != ShapeshiftForm.Moonkin),
                new Decorator(ret => !Me.Combat && Me.Specialization == WoWSpec.DruidBalance, AstralCommunion()),
                CastOnMe(PROWL, ret => !buffExists(PROWL, Me) && !Me.Combat && CRSettingsCat.myPrefs.useProwl && !spellOnCooldown(PROWL)),
                new Decorator(ret => Me.Combat && IsCrowdControlledPlayer(Me), RemoveRooted()),

                new Decorator(ret => IsInGame && Me.Specialization == WoWSpec.DruidFeral && !buffExists(VISIONS_OF_INSANITY_BUFF, Me) && !buffExists(ALCHEMY_FLASK_AGILITY_BUFF, Me) && NotHaveFlaskBuff && CRSettingsCat.myPrefs.AlchemyFlask && CanUseSpells(), AlchemyFlask()),
                new Decorator(ret => IsInGame && Me.Specialization == WoWSpec.DruidGuardian && !buffExists(VISIONS_OF_INSANITY_BUFF, Me) && !buffExists(ALCHEMY_FLASK_AGILITY_BUFF, Me) && NotHaveFlaskBuff && CRSettingsBear.myPrefs.AlchemyFlask && CanUseSpells(), AlchemyFlask()),
                new Decorator(ret => IsInGame && Me.Specialization == WoWSpec.DruidFeral && !buffExists(VISIONS_OF_INSANITY_BUFF, Me) && CRSettingsCat.myPrefs.Crystal && CanUseSpells() && NotHaveFlaskBuff, CrystalOfInsanity()),
                new Decorator(ret => IsInGame && Me.Specialization == WoWSpec.DruidGuardian && !buffExists(VISIONS_OF_INSANITY_BUFF, Me) && CRSettingsBear.myPrefs.Crystal && CanUseSpells() && NotHaveFlaskBuff, CrystalOfInsanity()),

                Cast("Aquatic Form", ret => !Me.Combat
                    && !buffExists("Prowl", Me)
                    && !Me.Mounted
                    && (Me.Specialization == WoWSpec.DruidFeral && CRSettingsCat.myPrefs.useAquaticForm
                    || Me.Specialization == WoWSpec.DruidGuardian && CRSettingsBear.myPrefs.useAquaticForm)
                    && Me.IsSwimming
                    && Me.Shapeshift != ShapeshiftForm.Aqua),

                
                CastOnMe(REJUVENATION, ret => !Me.Combat && Me.HealthPercent <= CRSettingsCat.myPrefs.RejuvenationOOC && !buffExists(REJUVENATION, Me) && CanUseSpells()),
                CastOnMe(HEALING_TOUCH, ret => !Me.Combat && Me.HealthPercent <= CRSettingsCat.myPrefs.HealingTouchOOC && CanUseSpells()),
                CastOnMe(MOTW, ret => !Me.Combat && NotHaveStatsBuffs() && CanUseSpells()),
                Cast(MIGHT_OF_URSOC, ret => Me.Combat && !spellOnCooldown(MIGHT_OF_URSOC) && Me.HealthPercent <= CRSettingsCat.myPrefs.MightOfUrsoc),
                Cast(BARKSKIN, ret => Me.Combat && !spellOnCooldown(BARKSKIN) && Me.HealthPercent <= CRSettingsCat.myPrefs.Barkskin),
                Cast(SURVIVAL_INSTINCTS, ret => Me.Combat && !spellOnCooldown(SURVIVAL_INSTINCTS) && Me.HealthPercent <= CRSettingsCat.myPrefs.SurvivalInstincts)
                );
        }
        #endregion

        #region Combat
        Composite CreateCombat()
        {
            return
                new PrioritySelector(
                new Decorator(ret => Paused || Me.IsFlying || (Me.Mounted && NotHaveRaidbot()), PauseCR()),
                FaceMyTarget(),
                new Decorator(ret => gotTarget && NeedGoBackwards, GoBackwards()),
                new Decorator(ret => gotTarget && Me.CurrentTarget.Distance > myRange && !NeedGoBackwards, CreateMovementBehavior()),
                new Decorator(ret => (Me.CurrentTarget == null || Me.CurrentTarget.IsFriendly) 
                    && AllowTargeting 
                    && !Me.CurrentMap.IsBattleground,
                    new Action(ret => { FindTarget(); return RunStatus.Failure; })),
                new Decorator(ret => IsCrowdControlledPlayer(Me) && BreakRooted, RemoveRooted()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidBalance, BoomkinRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidGuardian, GuardianRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidFeral && useBearForm(), BearRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidFeral && useCatForm(), CatRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.None && SpellManager.HasSpell(CAT_FORM), LowbieCat()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.None && !SpellManager.HasSpell(CAT_FORM), LowbieRotation())
                );
        }
        #endregion

        #region raidbot
        public bool NotHaveRaidbot()
        {
            return !usedBot.Contains("RAID") && !usedBot.Contains("COMBAT") && !usedBot.Contains("TYR");
        }
        #endregion

        #region bg
        public bool InBattleGround()
        {
            return Battlegrounds.IsInsideBattleground;
        }
        #endregion

        #region use items
        
        void UseEngiGloves()
        {
            var gloves = StyxWoW.Me.Inventory.Equipped.Hands;
            if (gloves != null && CanUseEquippedItem(gloves))
            
                gloves.Use();
            
        }
        void VirmenPotion()
        {
            var virmen = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 76089);
            if (virmen != null && virmen.Usable && virmen.Cooldown <= 0)
            {
                virmen.Use();
            }
        }
        
        
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
            {
                return false;
            }


            return item.Usable && item.Cooldown <= 0;
        }
        #endregion

        #region addcount
        IEnumerable<WoWUnit> UnfriendlyUnits
        {
            get
            {
                return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => !u.IsDead
                    && u.CanSelect
                    && u.Attackable
                    && u.IsHostile
                    && !u.IsCritter
                    && !u.IsNonCombatPet
                    && !u.Name.Contains("Dummy")
                    && u.IsWithinMeleeRange);
            }
        }
        #endregion

        #region spelcasting
        private delegate T Selection<out T>(object context);
        Composite CastMelees(string Spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, bool ignoreCanCast = false)
        {
            return
                new Decorator(ret =>
                {
                    if (reqs != null && !reqs(ret))
                        return false;
                    if (!ignoreCanCast && !SpellManager.CanCast(Spell, onTarget != null ? onTarget(ret) : Me.CurrentTarget))
                        return false;
                    return true;
                },
                            new Action(ret =>
                            {
                                WoWSpell castingSpell = Me.CastingSpell;
                                if (castingSpell != null && castingSpell.Name != Spell)
                                    Lua.DoString("SpellStopCasting()");
                                Logging.Write("Casting: " + Spell + " on " + Me.CurrentTarget.Name);
                                SpellManager.Cast(Spell, (onTarget != null ? onTarget(ret) : null));
                                LastSpell = Spell;
                            })
                    );
        }
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }
                        ));
        }
        Composite Cast(int spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        //Logging.Write(spell);
                        lastUsed = spell;
                    }
                        ));
        }
        Composite CastWildCharge(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell, Me.CurrentTarget);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }
                        ));
        }
        Composite CastOnMe(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell, Me);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }
                        ));
        }
        
        Composite CastMelee(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(ret => ((reqs != null && reqs(ret)) || (reqs == null))
                    && gotTarget
                    && SpellManager.HasSpell(spell)
                    && SpellManager.CanCast(spell) 
                    && Me.CurrentTarget.Distance <= 4,
                    new Action(ret =>
                    {
                        SpellManager.Cast(spell);
                        Logging.Write(spell);
                        LastSpell = spell;
                    }
                        ));
        }
        #endregion

        #region Kind of target
        public bool IsWoWBoss(WoWUnit mytarget)
        {
            if (StyxWoW.Me.CurrentTarget != null)
            {
                if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
                {
                    return true;
                }
                else if (target.IsBoss(mytarget))
                {
                    return true;
                }
                else if (Me.CurrentTarget.MaxHealth >= (100 * 1000000)) { return true; }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.RareElite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                    && StyxWoW.Me.CurrentTarget.MaxHealth >= (StyxWoW.Me.MaxHealth * 3)
                    && (!StyxWoW.Me.GroupInfo.IsInParty
                    || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                    && !StyxWoW.Me.GroupInfo.IsInRaid
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.Name.Contains("Dummy")
                    && !StyxWoW.Me.IsInInstance)
                {
                    return true;
                }
                else if (StyxWoW.Me.CurrentTarget.IsPlayer
                    && !StyxWoW.Me.CurrentTarget.IsFriendly)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion Kind of Target

        #region pause
        public static bool PauseAoe = false;
        public static bool Paused = false;
        public static bool SwitchBearForm = false;
        public static bool MovementKeyPressed = false;

        public static void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (SettingsExtraKittyFeral.myPrefs.StopCRKey == SettingsExtraKittyFeral.Keypress.NONE
                && SettingsExtraKittyFeral.myPrefs.StopAoeKey == SettingsExtraKittyFeral.Keypress.NONE
                && SettingsExtraKittyFeral.myPrefs.BearFormKeys == SettingsExtraKittyFeral.Keypress.NONE)
            {
                return;
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                string pauseMyAoe = "AOE cancelled, press " + SettingsExtraKittyFeral.myPrefs.StopAoeKey.ToString() + " in WOW again to turn AOE back on";
                if (args.Args[0].ToString() == SettingsExtraKittyFeral.myPrefs.StopAoeKey.ToString())
                {
                    PauseAoe = !PauseAoe;
                    if (PauseAoe)
                    {
                        Logging.Write("Aoe cancelled, press {0} in WOW again to resume Aoe",
                                     SettingsExtraKittyFeral.myPrefs.StopAoeKey.ToString());
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseMyAoe + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Aoe Resumed");
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Aoe Resumed !\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == SettingsExtraKittyFeral.myPrefs.BearFormKeys.ToString())
                {
                    SwitchBearForm = !SwitchBearForm;
                    if (SwitchBearForm)
                    {
                        string backBear = "Switching to Bear Form, press " + SettingsExtraKittyFeral.myPrefs.BearFormKeys.ToString() + " in WOW again to switch back to Cat Form";

                        Logging.Write("Switching to Bear Form, press {0} in WOW again to switch back to Cat Form",
                                     SettingsExtraKittyFeral.myPrefs.BearFormKeys.ToString());
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + backBear + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Switching back to Cat Form !");
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Switching back to Cat Form !\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == SettingsExtraKittyFeral.myPrefs.StopCRKey.ToString())
                {
                    string pauseCR = "CR paused, press " + SettingsExtraKittyFeral.myPrefs.StopCRKey.ToString() + " in WOW again to turn back on";
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("CR paused, press {0} in WOW again to turn back on",
                                     SettingsExtraKittyFeral.myPrefs.StopCRKey.ToString());
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"" + pauseCR + "\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("CR running again ....");
                        if (SettingsExtraKittyFeral.myPrefs.PrintRaidstyleMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"CR running again ....\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause

        #region solo or not
        public bool SoloOrNot()
        {
            return (!StyxWoW.Me.GroupInfo.IsInParty || StyxWoW.Me.GroupInfo.NumPartyMembers <= 3)
                && !StyxWoW.Me.GroupInfo.IsInRaid
                && !StyxWoW.Me.IsInInstance;
        }
        #endregion

        #region useCatForm
        public bool useCatForm()
        {
            return SpellManager.HasSpell(CAT_FORM)
                && Me.Specialization != WoWSpec.DruidGuardian
                && Me.Specialization != WoWSpec.DruidBalance
                && !SwitchBearForm
                && !buffExists(MIGHT_OF_URSOC, Me);
        }
        #endregion useCatForm

        #region useBearForm
        public bool useBearForm()
        {
            return SpellManager.HasSpell(BEAR_FORM)
                && Me.Specialization != WoWSpec.DruidGuardian
                && Me.Specialization != WoWSpec.DruidBalance
                && (SwitchBearForm
                || buffExists(MIGHT_OF_URSOC, Me)
                || (addCount >= CRSettingsCat.myPrefs.startBearAoe && !Me.GroupInfo.IsInRaid && !Me.IsInInstance));
        }
        #endregion useBearForm

        #region useNoForm
        public bool useNoForm()
        {
            return !SpellManager.HasSpell(CAT_FORM);
        }
        #endregion

        #region spells
        public string MIGHT_OF_URSOC = "Might of Ursoc";
        public string CAT_FORM = "Cat Form";
        public string BEAR_FORM = "Bear Form";
        public string WRATH = "Wrath";
        public string MOONFIRE = "Moonfire";
        public string REJUVENATION = "Rejuvenation";
        public string HEALING_TOUCH = "Healing Touch";
        public int HEALING_TOUCH_INT = 0;
        public string FAERIE_FIRE = "Faerie Fire";
        public string FAERIE_SWARM = "Faerie Swarm";
        public string WEAKENED_ARMOR = "Weakened Armor";
        public string RAKE = "Rake";
        public string RIP = "Rip";
        public string SAVAGE_ROAR = "Savage Roar";
        public string LIFEBLOOD = "Lifeblood";
        public string TIGERS_FURY = "Tiger's Fury";
        public string FEROCIOUS_BITE = "Ferocious Bite";
        public string PREDATORY_SWIFTNESS = "Predatory Swiftness";
        public string INCARNATION = "Incarnation";
        public string WILD_CHARGE = "Wild Charge";
        public int CLEARCASTING = 135700;
        public string THRASH = "Thrash";
        public string BERSERKING = "Berserking";
        public string BERSERK = "Berserk";
        public string MANGLE = "Mangle";
        public string RAVAGE = "Ravage";
        public string SHRED = "Shred";
        public string SWIPE = "Swipe";
        public string SKULL_BASH = "Skull Bash";
        public string MIGHTY_BASH = "Mighty Bash";
        public string MAUL = "Maul";
        public string LACERATE = "Lacerate";
        public string BEAR_MANGLE = "Mangle";
        public string BEAR_SWIPE = "Swipe";
        public string BEAR_THRASH = "Thrash";
        public string BEAR_FAERIE_FIRE = "Faerie Fire";
        public string BARKSKIN = "Barkskin";
        public string SURVIVAL_INSTINCTS = "Survival Instincts";
        public string SAVAGE_DEFENSE = "Savage Defense";
        public string FRENZIED_REGENERATION = "Frenzied Regeneration";
        public string SON_OF_URSOC = "Son of Ursoc";
        public int TOOTH_AND_CLAW = 135286;
        public int DREAM_OF_CENARIUS_BEAR = 145162;
        public string FORCE_OF_NATURE = "Force of Nature";
        public string PROWL = "Prowl";
        public string POUNCE = "Pounce";
        public string GROWL = "Growl";
        public int WEAKENED_BLOWS = 115798;
        public int THRASH_CAT = 106830;
        public string WAR_STOMP = "War Stomp";
        public string CENARION_WARD = "Cenarion Ward";
        public string BONE_SHIELD = "Bone Shield";
        public string CONSECRATION = "Consecration";
        public string ELUSIVE_BREW = "Elusive Brew";
        //Flasks
        public int ALCHEMY_FLASK_AGILITY_BUFF = 79639;
        public int VISIONS_OF_INSANITY_BUFF = 127230;

        //end flasks
        public string ENRAGE = "Enrage";

        #endregion spells

        #region CanUseSpells
        public bool CanUseSpells()
        {
            return !Me.Mounted && !Me.IsFlying && !Me.OnTaxi && !Me.IsOnTransport;
        }
        #endregion

        #region force of nature
        public Stopwatch FoNTimer = new Stopwatch();
        public bool UseForceOfNaure
        {
            get
            {
                if (FoNTimer.IsRunning && FoNTimer.ElapsedMilliseconds <= 16000) { return false; }

                if (LastSpell != FORCE_OF_NATURE && !spellOnCooldown(FORCE_OF_NATURE))
                {
                    FoNTimer.Reset();
                    FoNTimer.Start();
                    return true;
                }
                return false;
            }
        }
        #endregion

        #region wildcharge
        public bool CanCastWildCharge(float left, float right)
        {
            return gotTarget && Me.CurrentTarget.Distance >= left && Me.CurrentTarget.Distance <= right;
        }
        #endregion

        #region pause CR
        Composite PauseCR()
        {
            return new Action(ret => { return; });
        }
        #endregion

        #region gotTarget
        public bool gotTarget
        {
            get
            {
                return Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && Me.CurrentTarget.CanSelect && Me.CurrentTarget.Attackable && !Me.CurrentTarget.IsMe;
            }
        }
        #endregion

        #region do not pull
        public bool DoNotPullOrDismount
        {
            get
            {
                return usedBot.Contains("LAZY")
                    || usedBot.Contains("RAID")
                    || usedBot.Contains("TYR")
                    || usedBot.Contains("COMBAT")
                    || usedBot.Contains("GATHER");
            }
        }
        #endregion

        #region loot
        private double LootRange
        {
            get { return LootTargeting.LootRadius; }
        }
        private IOrderedEnumerable<WoWUnit> Lootables
        {
            get
            {
                var targetsList = ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(
                        p => (p.Lootable || p.CanSkin) && p.Distance <= LootRange).OrderBy(l => l.Distance);
                return targetsList;
            }
        }
        private void GetLoot()
        {
            if (Me.IsCasting || Lootables.Count() == 0 || Me.IsMoving)
                return;
            if (LootFrame.Instance != null && LootFrame.Instance.IsVisible)
            {
                LootFrame.Instance.LootAll();
                return;
            }
            var lootTarget = Lootables.FirstOrDefault();
            if (lootTarget.Distance > lootTarget.InteractRange && !Me.GroupInfo.IsInParty && !Me.GroupInfo.IsInRaid && !Me.IsInInstance)
            {
                slog("Moving to loot {0}.", lootTarget.Name);
                Navigator.MoveTo(lootTarget.Location);
            }
            else
            {
                lootTarget.Interact();
                return;
            }
        }
        #endregion loot

        Composite THRASH_AOE()
        {
            return new Decorator(
                new Action(ret =>
                {
                    if (SpellManager.HasSpell(THRASH)
                        && gotTarget
                        && Me.CurrentTarget.Distance <= 4
                        && LastSpell != THRASH
                        && (buffExists(CLEARCASTING, Me) || Me.EnergyPercent >= 50)
                        && !debuffExists(THRASH, Me.CurrentTarget)
                        && SpellManager.CanCast(THRASH))
                    {
                        SpellManager.Cast(THRASH);
                        Logging.Write(Colors.Orange, "Thrash Aoe");
                        LastSpell = THRASH;
                    }
                    return RunStatus.Failure;
                }));
        }
    }
}
